package edu.hawaii.halealohacli;

import java.util.AbstractList;
import org.wattdepot.client.WattDepotClient;

/**
 * Command: contains currently implemented commands for accessing the WattDepot server.
 * 
 * @author John MacMillan
 * @author Mitchell Kupfer
 * @author Bryson Hori
 * @author Chris Fang
 * @author Chris Wilson
 * @author Daniel Ly
 * @author Jordan Do
 * 
 */
public class Command implements CommandInterface {
  Baselist baseList;
  // user inputs with position 0 being the command.
  AbstractList<String> strings;
  WattDepotClient client;

  /**
   * Issues the commands.
   * 
   * @param strings the array of user arguments.
   * @param client the WattDepot client.
   * @param baseList HashMap<String, double[]> containing list of baselines
   */
  public Command(AbstractList<String> strings, WattDepotClient client, Baselist baseList) {
    this.strings = strings;
    this.client = client;
    this.baseList = baseList;
  }

  /**
   * Calls and executes the commands.
   * 
   * @return boolean, true if succeeds.
   */
  public boolean executeCommand() {
    try {

      if (strings.get(0).equalsIgnoreCase("current-power")) {
        return currentPower(strings.get(1));
      }
      else if (strings.get(0).equalsIgnoreCase("help")) {
        return help();
      }
      else if (strings.get(0).equalsIgnoreCase("daily-energy")) {
        return dailyEnergy(strings.get(1), strings.get(2));
      }
      else if (strings.get(0).equalsIgnoreCase("energy-since")) {
        return energySince(strings.get(1), strings.get(2));
      }
      else if (strings.get(0).equalsIgnoreCase("rank-towers")) {
        return rankTowers(strings.get(1), strings.get(2));
      }
      else if (strings.get(0).equalsIgnoreCase("set-baseline")) {
        if (strings.size() == 2) {
          return setBaseline(strings.get(1));
        }
        else {
          return setBaseline(strings.get(1), strings.get(2));
        }
      }
      else if (strings.get(0).equalsIgnoreCase("monitor-power")) {
        if (strings.size() == 2) {
          return monitorPower(strings.get(1));
        }
        else {
          return monitorPower(strings.get(1), strings.get(2));
        }
      }
      else if (strings.get(0).equalsIgnoreCase("monitor-goal")) {
        return monitorGoal(strings.get(1), strings.get(2), strings.get(3));
      }
      else {
        return false;
      }

    }

    catch (Exception e) {
      return false;
    }
  }

  /**
   * Calls daily-energy command.
   * 
   * @param tower the tower the user specified.
   * @param date the date of the day.
   * @return boolean false if fails.
   */
  public boolean dailyEnergy(String tower, String date) {
    DailyEnergy dailyEnergy = new DailyEnergy(tower, date, client);
    boolean value = false;
    try {
      value = dailyEnergy.run();
    }
    catch (Exception e) {
      System.out.println("Error occured while running daily-energy.");
    }
    return value;
  }

  /**
   * Rank towers command.
   * 
   * @param date1 the start date.
   * @param date2 the end date.
   * @return boolean false if fails.
   */
  public boolean rankTowers(String date1, String date2) {
    try {
      RankTowers rankTowers = new RankTowers(date1, date2, client);
      return rankTowers.run();
    }
    catch (Exception e) {
      System.out.println("Enter dates as YYYY-MM-DD \n Older data may not be valid.");
      return false;
    }
  }

  /**
   * Finds the energy since a given date.
   * 
   * @param tower the tower to find energy for.
   * @param date the start date.
   * @return boolean false if fails.
   */
  public boolean energySince(String tower, String date) {
    EnergySince energySince = new EnergySince(tower, date, client);
    boolean value = false;
    try {
      value = energySince.run();
    }
    catch (Exception e) {
      System.out.println("Error occured while trying to run energy-since.");
    }
    return value;
  }

  /**
   * Get the current power of a tower.
   * 
   * @param tower the tower specified by user.
   * @return boolean false if fails.
   */
  public boolean currentPower(String tower) {
    CurrentPower currentPower = new CurrentPower(tower, client);
    boolean value = true;
    try {
      value = currentPower.run();
    }
    catch (Exception e) {
      System.out.println("Error occured while trying run current-power.");
    }
    return value;
  }

  /**
   * Monitor the current power of a tower.
   * 
   * @param tower the tower specified by user.
   * @return boolean false if fails.
   */
  public boolean monitorPower(String tower) {
    MonitorPower monitorPower = new MonitorPower(tower, client);
    boolean value = true;
    try {
      value = monitorPower.run();
    }
    catch (Exception e) {
      System.out.println("Error occured while trying run monitor-power.");
    }
    return value;
  }

  /**
   * Monitor the current power of a tower.
   * 
   * @param tower the tower specified by user.
   * @param interval the interval to get power specified by user.
   * @return boolean false if fails.
   */
  public boolean monitorPower(String tower, String interval) {
    int convertedInterval;
    try {
      convertedInterval = Integer.parseInt(interval);
    }
    catch (NumberFormatException nfe) {
      System.out.println("Invalid interval, must be a positive integer");
      return false;
    }
    if (convertedInterval <= 0) {
      System.out.println("Invalid interval, must be a positive integer");
      return false;
    }
    MonitorPower monitorPower = new MonitorPower(tower, client, convertedInterval);
    boolean value = true;
    try {
      value = monitorPower.run();
    }
    catch (Exception e) {
      System.out.println("Error occured while trying run monitor-power.");
    }
    return value;
  }

  /**
   * Setting the baseline for a tower's consumed energy per hour in a day. Defaults to yesterday if
   * no date is given.
   * 
   * @param tower the tower specified by user.
   * @return boolean false if fails.
   */
  public boolean setBaseline(String tower) {
    SetBaseline setBaseline = new SetBaseline(tower, client);
    boolean value = true;
    try {
      // check that date is valid
      value = setBaseline.run();
      // remove any previous baseline for this tower
      baseList.remove(tower);
      // add the baseline data and tower to list
      baseList.put(tower, setBaseline.trueRun());
    }
    catch (Exception e) {
      System.out.println("Error occured while trying to run set-baseline.");
    }
    return value;
  }

  /**
   * Setting the baseline for a tower's consumed energy in a day. Defaults to yesterday if no date
   * is given.
   * 
   * @param tower the tower specified by user.
   * @param date the date specified
   * @return boolean false if fails.
   */
  public boolean setBaseline(String tower, String date) {
    SetBaseline setBaseline = new SetBaseline(tower, date, client);
    boolean value = true;
    try {
      // check that date is valid
      value = setBaseline.run();
      // remove any previous baseline data for this tower
      baseList.remove(tower);
      // add to list
      baseList.put(tower, setBaseline.trueRun());
    }
    catch (Exception e) {
      System.out.println("Error occured while trying to run set-baseline.");
    }
    return value;
  }

  /**
   * Comparing current power consumption with a goal based from a given percentage of a
   * pre-determined baseline.
   * 
   * @param tower the tower specified by user.
   * @param goal the goal specified
   * @param interval the interval specified
   * @return boolean false if fails.
   */
  public boolean monitorGoal(String tower, String goal, String interval) {
    int convertedGoal;
    int convertedInterval;
    try {
      convertedGoal = Integer.parseInt(goal);
    }
    catch (NumberFormatException nfe) {
      System.out.println("Invalid goal, must be a positive integer between 1 and 99");
      return false;
    }
    if (convertedGoal < 1 || convertedGoal > 99) {
      return false;
    }
    try {
      convertedInterval = Integer.parseInt(interval);
    }
    catch (NumberFormatException nfe) {
      System.out.println("Invalid interval, must be a positive integer");
      return false;
    }
    if (convertedInterval <= 0) {
      return false;
    }
    MonitorGoal monitorGoal =
        new MonitorGoal(tower, client, convertedGoal, convertedInterval, baseList);
    boolean value = true;
    try {
      value = monitorGoal.run();
    }
    catch (Exception e) {
      System.out.println("Error occured while trying run monitor-goal.");
    }
    return value;
  }

  /**
   * The help command, prints commands.
   * 
   * @return boolean false if fails.
   */
  public boolean help() {
    Help help = new Help();
    return help.run();
  }

}
